<template>
  <div :class="['anvil-code-form', formClass]">
    <avue-form
      v-if="showForm"
      v-model="formData"
      :option="options"
      :upload-before="uploadBefore"
      :upload-after="uploadAfter"
      :upload-preview="uplodaPreview"
      @submit="handleDialogSubmit"
      ref="avueForm"
    >
      <template #[item.prop] v-for="item in optionColumn" :key="item.uuid">
        <!-- 特定组件绑定formdata，但是性能压力增加 -->
        <custom-comp-item
          v-model="formData[item.prop]"
          v-model:formData="formData"
          v-if="isProvideFormData(item.type)"
          :item="item"
          :params="item.params"
          :ref="generateRef(item)"
          :optionColumn="optionColumn"
          @close-and-refresh="handleParentRefresh"
          @close-and-set="handleSetFormDataByEmit"
        />
        <!-- 基本组件只绑定value值，而不绑定formdata，否则影响性能 -->
        <custom-comp-item
          v-model="formData[item.prop]"
          v-else
          :item="item"
          :params="item.params"
          :ref="generateRef(item)"
          :optionColumn="optionColumn"
          @close-and-refresh="handleParentRefresh"
          @close-and-set="handleSetFormDataByEmit"
        />
      </template>
    </avue-form>
    <el-skeleton v-else-if="!noSkeleton" animated :rows="5"></el-skeleton>
  </div>
</template>
<script>
import {
  initCompsRef,
  setCompsRefShow,
  findCompsRef,
  deletePropNoRef,
  generateFormRules,
  handleDefaultDateTime,
  handleDefaultDateTimeRange,
  handleOptionTrans,
  generateRef,
  executeFunctionsInOrder,
  customApiExecute,
  modelApiExecute,
  localApiExecute,
  getZfsUploadTrans,
  generateFileUrlByFileId,
  generateFileUrl,
  forceUpdateParentForm,
  getDisplayRule,
  isExistDisplayRule,
  getJsonCallableCompList,
  customUploadByApi,
  generateStyleSheet,
  initDisabledCompsRef,
  setCompsRefEnable
} from '../../utils/common-methods';
import { handleValueTrans, handleValueTransBack } from '../../utils/compValTrans';
import * as formulajs from '@formulajs/formulajs';
import customCompItem from './customCompItem.vue';
import defaultSettings from '@/settings';
import { getDynamicCompDicts } from '../../utils/getDicts';
import { ajax } from '@/utils/ajax';
import jp from 'jsonpath';
import { useAnvilCodeStore } from '../../store/modules/code';
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';
import { debounceWrapper } from '@/utils/zmids';
import { getToken } from '@/utils/auth';
import { cloneDeep, difference } from 'lodash-es';
import { provideFormData, defaultDateGenerate, defaultDateRangeGenerate } from '../../utils/specialCompTypes';

export default {
  name: 'FormRender',
  components: { customCompItem },
  inject: ['getDataFromOthers'],
  props: {
    data: {
      type: Object,
      default: () => {}
    },
    options: {
      type: Object,
      default: () => {}
    },
    // 每个表单的唯一标识，由页面管理携带过来
    pageId: {
      type: String,
      default: ''
    },
    // 不显示骨架屏
    noSkeleton: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      formData: {},
      compsRefWatcher: undefined,
      formulaWatcher: undefined,
      displayRulesWatcher: undefined,
      dynamicKArr: [],
      formulaData: [],
      uniqProps: [],
      showSubmitConfirm: false,
      confirmLoading: false,
      showAdditionalDialog: false,
      localOptions: [],
      showForm: false, // 标志位，用于在所有表单配置加载完毕后渲染
      generateRef
    };
  },
  computed: {
    allColumns() {
      let arr = [];

      if (this.options.column) {
        this.options.column.map((col) => {
          col.pageId = this.pageId;
        });
        arr = [...this.options.column];
      }

      // 将group中组件取出
      if (this.options.group) {
        this.options.group.map((group) => {
          const { column } = group;
          column.map((col) => {
            delete col.parentName;
            col.pageId = this.pageId;
          });
          arr.push(...column);
        });
      }

      return arr;
    },
    optionColumn() {
      let arr = [];
      if (this.options && this.allColumns && this.allColumns.length) {
        this.allColumns.forEach((item) => {
          if (item.widget || (item.dataRef && item.dataRef.contactModelVersionId)) {
            arr.push(item);
          }
        });
      }
      return arr;
    },
    lifeCycle() {
      if (this.options && this.options.lifecycle) {
        return this.options.lifecycle;
      } else {
        return [];
      }
    },
    // 当前表单是否处于子表单内部，目前以组件是否有parentName字段作为判断标准
    isDynamicChild() {
      return !!this.allColumns.find((opt) => opt.parentName);
    },
    baseUrl() {
      return import.meta.env.VITE_APP_BASE_API;
    },
    // 从层级中拉平获取所有非容器组件列表
    allFlattedColumns() {
      return getJsonCallableCompList(this.options);
    },
    formClass() {
      return this.options.formClass ? this.options.formClass.join(' ') : '';
    }
  },
  watch: {
    data: {
      handler(newVal, oldVal) {
        if (newVal) {
          this.formData = newVal;
        }
      },
      deep: true,
      immediate: true
    },
    formData: {
      handler(newVal, oldVal) {
        if (this.$attrs.inGrid) {
          console.log('栅格布局内主表单form改变', JSON.stringify(newVal));
        } else {
          console.log('主表单form改变', JSON.stringify(newVal));
        }

        // 待优化，不能每次变化都监听
        this.handleFormDataChange(newVal);
      },
      deep: true,
      immediate: true
    },
    'options.column': {
      handler(newVal) {
        this.handleFormJsonChange(newVal);
      },
      deep: true,
      immediate: true
    },
    options: {
      handler(newVal) {
        if (newVal) {
          console.log('options改变');
          handleOptionTrans(newVal);
          this.localOptions = newVal;
        }
      },
      deep: true,
      immediate: true
    },
    localOptions: {
      handler(newVal) {
        this.$emit('update:options', newVal);
      },
      deep: true
    }
  },
  async mounted() {
    this.rewriteAvueForm();
    await this.init();
  },
  created() {},
  beforeUnmount() {},
  methods: {
    async init() {
      await this.initFormJson();
      generateStyleSheet(this.options.classes);
      await this.initFormData();
      await this.handleMountedLifeCycleList();
    },
    compsAllForula(data) {
      data.forEach((item) => {
        if (item.children && item.children.column.length > 0) {
          // item.children.column.forEach((cols) => {
          //   cols.parentName = item.prop;
          // });
          this.compsAllForula(item.children.column);
        }
        if (item.formula) {
          this.formulaData.push(item);
        }
      });
      return this.formulaData;
    },
    async handleDialogSubmit(form, done) {
      const checkAnvil = await this.checkAnvil();
      // 先校验子表单内容，若失败则返回
      if (!checkAnvil.valid) {
        done();
        return;
      }
      this.formSubmit(form, done);
    },
    // 表单数据提交
    formSubmit(form, done, resolveCallback, rejectCallback) {
      this.$emit('handleDialogSubmit', form, done, resolveCallback, rejectCallback);
    },
    resetForm() {
      console.log('触发formRender重置');
      this.$refs.avueForm.resetForm();
    },
    resetFields() {
      this.$refs.avueForm.resetFields();
    },
    validate(func, config) {
      return this.$refs.avueForm.validate(async (valid, done, fields) => {
        const checkAnvil = config ? await this.checkAnvil(config) : { valid: true, fields: {} };
        const newValid = valid && checkAnvil.valid;
        const newFields = Object.assign(fields, checkAnvil.fields);
        if (func && typeof func == 'function') {
          func(newValid, done, newFields);
        }
      });
    },
    submit() {
      this.$refs.avueForm.submit();
    },
    // 重置表单数据并重新执行生命周期方法
    async reload() {
      this.$refs.avueForm.resetFields();
      this.formData = {};
      this.showForm = false;
      await this.init();
    },
    // 作为弹框内页面时，传递消息关闭自身弹框并刷新原页面
    closeAndRefresh() {
      console.log('开始触发closeAndRefresh');
      this.$emit('closeAndRefresh');
    },
    closeAndSet(data) {
      console.log('开始触发closeAndSet,参数为', data);
      this.$emit('closeAndSet', data);
    },
    onlyClose() {
      console.log('开始触发onlyClose');
      this.$emit('onlyClose');
    },
    // 作为弹框页面的父页面，接收到刷新页面的消息，找到父页面并刷新
    handleParentRefresh(type) {
      // 可能存在有多个组件传出该事件，符合组件类型的才进行响应
      if (type == 'anvilDialog' || type == 'anvilDrawer') {
        console.log('当前页面为', this.pageId, '即将对父页面刷新');
        forceUpdateParentForm(this.pageId);
      }
    },
    handleSetFormDataByEmit(type, data) {
      // 可能存在有多个组件传出该事件，符合组件类型的才进行响应
      if (type == 'anvilDialog' || type == 'anvilDrawer') {
        console.log('当前页面为', this.pageId, '即将设置表单对象');
        this.setFormData(data);
      }
    },
    getFormData() {
      const outData = cloneDeep(this.formData);
      this.handleDataPropTrans(outData);
      return outData;
    },
    setFormData(data) {
      const inData = cloneDeep(data);
      this.handleDataPropTransBack(inData);
      this.formData = inData;
    },
    // 根据配置调用的刷新方法
    refresh() {
      this.handleLifeCycles('iframe');
    },
    // 对特定组件的字段表单值进行处理后传递出去
    handleDataPropTrans(data) {
      if (this.allFlattedColumns != null && this.allFlattedColumns.length > 0) {
        this.allFlattedColumns.forEach((e) => {
          handleValueTrans(data, e);
        });
      }
    },
    // 收到表单对象之后对特定组件值进行转化再赋值
    handleDataPropTransBack(data) {
      if (this.allFlattedColumns != null && this.allFlattedColumns.length > 0) {
        this.allFlattedColumns.forEach((e) => {
          handleValueTransBack(data, e);
        });
      }
    },
    getDataOutside() {
      if (this.getDataFromOthers && typeof this.getDataFromOthers === 'function') {
        // 此时应该处理row值与表单值关系，取两个对象合集
        let outData = this.getDataFromOthers();
        // outData.row = {
        //   ...outData.row,
        //   ...this.formData
        // };

        return outData;
      } else {
        return {};
      }
    },
    async validateAvueForm(func) {
      const res = this.$refs.avueForm.$refs.form.validate(func);
      return res;
    },
    // 函数公式计算
    // 判断当前组件中是否有配置公式的，不应该每次都开启监听
    watchFormula() {
      this.formulaData = [];
      let dataObj = this.compsAllForula(this.allColumns);

      if (dataObj.length) {
        this.formulaWatcher = this.$watch(
          'formData',
          // 增加防抖，在处理大批量数据导入时避免卡死
          debounceWrapper(function () {
            // 用于记录在window全局注册的变量，在计算完成之后删除
            const windowVars = [];

            // debugger
            // 不能删除此处的函数引入，否则动态赋值时无法找到
            let { SUM, ABS, CONCATENATE, IF, AVERAGE, INT, MAX, MIN, PRODUCT, SUMPRODUCT, COUNTIF, SUMIFS } = formulajs;
            // 子表单字段
            this.allColumns.forEach((item) => {
              if (item.type == 'anvilDynamic') {
                for (let key in this.formData) {
                  if (item.prop == key && this.formData[key] instanceof Array) {
                    this.formData[key].forEach((formItem) => {
                      for (let dynamicKey in formItem) {
                        window[item.prop + '_' + dynamicKey] = [];
                        windowVars.push(item.prop + '_' + dynamicKey);
                        this.formData[key].forEach((dataItem) => {
                          window[item.prop + '_' + dynamicKey].push(dataItem[dynamicKey]);
                        });
                      }
                    });
                  }
                }
              }
            });

            for (let key in this.formData) {
              window[key] = this.formData[key];
              windowVars.push(key);
            }

            dataObj.forEach((element) => {
              if (element.formula && element.formula.includes('&gt;')) {
                element.formula = element.formula.replace(/&gt;/g, '>');
              }
              if (element.formula && element.formula.includes('&lt;')) {
                element.formula = element.formula.replace(/&lt;/g, '<');
              }
              try {
                let newData = eval(element.formula);
                this.formData[element.prop] = newData;
                // this.$set(this.data, element.prop, newData);
              } catch (err) {}
            });
            console.log('目前的全局变量', windowVars);
            windowVars.map((v) => {
              delete window[v];
            });
          }),
          {
            deep: true
          }
        );
      }
    },
    // 在打开页面时对组件联动显隐数据进行监听
    watchCompsRef() {
      const compsWithRef = findCompsRef(this.allColumns);

      if (compsWithRef && compsWithRef.length) {
        this.compsRefWatcher = this.$watch(
          'formData',
          (newVal, oldVal) => {
            // 等待computed计算完毕后执行
            this.$nextTick(() => {
              // 记录本次display不需要被重置为false的组件
              const allHasShowComps = [];
              for (let key in this.formData) {
                const data = this.formData[key];
                const column = this.allColumns.find((col) => col.prop == key);
                if (column && column.dicData) {
                  column.dicData.map((dict) => {
                    const { value, compsRef } = dict;
                    if (value == data) {
                      const propList = setCompsRefShow(this.allColumns, compsRef);
                      allHasShowComps.push(...propList);
                    }
                  });
                }
              }
              console.log('所有联动组件', compsWithRef);
              console.log('不需要重置的联动组件', allHasShowComps);
              const compsNeedInit = difference(compsWithRef, allHasShowComps);
              console.log('需要重置的联动组件', compsNeedInit);
              initCompsRef(this.allColumns, compsNeedInit);
              deletePropNoRef(this.allColumns, this.formData);
            });
          },
          {
            deep: true
          }
        );
      }
    },
    // 监听下拉框/单选框组/复选框组选项间联动
    watchOptionsRelated() {
      const list = this.filterPropsWithOptionsRelated();
      list.map((itemProp) => {
        this.$watch(
          'formData.' + itemProp,
          function (newVal, oldVal) {
            if (newVal != oldVal) {
              //当前操作行
              let column = this.allColumns.find((col) => col.prop == itemProp);

              const compsRelated = [];
              // 找出所有与当前组件有关联的
              column.dicData.map((dict) => {
                if (dict && dict.connectChild) {
                  dict.connectChild.map((item) => {
                    compsRelated.push(item.childprop);
                  });
                }
              });

              const compsRelatedUniq = [...new Set(compsRelated)];
              this.resetColsDicData(compsRelatedUniq);
              if (column && column.dicData) {
                // 找到操作行选中的字典值
                let dict = column.dicData.find((dict) => dict.value == newVal);
                if (dict && dict.connectChild) {
                  // 当前组件每一个字典项关联的组件，对其字典进行重新取值
                  dict.connectChild.forEach((itemConChild, indexConChild) => {
                    // 关联组件index
                    const columnChildIndex = this.allColumns.findIndex((col) => col.prop == itemConChild.childprop);

                    // 存在
                    if (itemConChild.childprop != '') {
                      const arr = [];
                      itemConChild.childValue.forEach((childValueItem, childValueItemIndex) => {
                        let resultObj = this.allColumns[columnChildIndex].copyDicData.find((col) => col.value == childValueItem.value);
                        arr.push(JSON.parse(JSON.stringify(resultObj)));
                      });
                      this.localOptions.column[columnChildIndex].dicData = arr;
                      // this.changeOptions(this.allColumns, columnChildIndex, dicData, arr)
                      this.formData[itemConChild.childprop] = this.allColumns[columnChildIndex].type == 'checkbox' ? [] : '';
                    }
                  });
                }
              }
            }
          },
          {
            deep: true
          }
        );
      });
    },
    // 校验anvil表单，如自定义的校验规则、子表单内部、栅格布局内部等原生avue不提供的校验功能
    async checkAnvil(config) {
      let checkResAll = [],
        checkFieldsAll = {};
      const dynamicRulesMap = config ? config.dynamicRulesMap : undefined;
      const mainFormRules = config ? config.mainFormRules : undefined;
      // 处理主表单的规则校验
      if (mainFormRules) {
        const mainRulesResult = this.operateValidateRules(mainFormRules);
        checkResAll.push(mainRulesResult);
      }
      // 处理子表单等组件内部校验
      if (this.$refs && Object.keys(this.$refs).length) {
        for (let key in this.$refs) {
          const ref = this.$refs[key];
          if (key.includes('dynamicItem')) {
            const res = await this.checkDynamic(ref, dynamicRulesMap);
            checkResAll.push(res.valid);
            Object.assign(checkFieldsAll, res.fields);
          } else if (key.includes('gridItem')) {
            const res = await this.checkGrid(ref);
            checkResAll.push(res.valid);
            Object.assign(checkFieldsAll, res.fields);
          } else if (key.includes('tabsItem')) {
            const res = await this.checkTabs(ref);
            checkResAll.push(res.valid);
            Object.assign(checkFieldsAll, res.fields);
          }
        }
      }

      console.log('checkResAll', checkResAll);
      console.log('checkFieldsAll', checkFieldsAll);
      // 最后生成一个校验结果数组，若存在false则证明校验失败
      return { valid: !checkResAll.some((item) => item === false), fields: checkFieldsAll };
    },
    // 对内部子表单进行校验,调用custom-comp-item组件的校验方法
    async checkDynamic(ref, dynamicRulesMap) {
      let checkRes = true,
        fields = {},
        ruleIds = undefined;
      // 找到子表单组件数据结构
      const { item } = ref;
      if (dynamicRulesMap && item && dynamicRulesMap[item.uuid]) {
        ruleIds = dynamicRulesMap[item.uuid];
      }
      const res = ref.validateDynamic(ruleIds);

      try {
        await Promise.all(res);
      } catch (e) {
        checkRes = false;
        fields = e;
      }
      return {
        valid: checkRes,
        fields
      };
    },
    // 对栅格布局内部组件进行校验
    async checkGrid(ref) {
      let checkRes = true,
        fields = {};
      const res = ref.validateGrid();

      try {
        await Promise.all(res);
      } catch (e) {
        checkRes = false;
        fields = e;
      }
      return { valid: checkRes, fields };
    },
    async checkTabs(ref) {
      let checkRes = true,
        fields = {};
      const res = ref.validateTabs();

      try {
        await Promise.all(res);
      } catch (e) {
        checkRes = false;
        fields = e;
      }
      return { valid: checkRes, fields };
    },
    // 重置栅格布局内部组件
    resetGrid() {
      if (this.$refs && Object.keys(this.$refs).length) {
        for (let key in this.$refs) {
          const ref = this.$refs[key];
          if (key.includes('gridItem')) {
            ref.resetGrid();
          }
        }
      }
    },
    // 重写avueform方法以及改写属性
    rewriteAvueForm() {
      if (this.$refs.avueForm) {
        console.log('this.$refs.avueForm.$refs.form', this.$refs.avueForm);

        const originSubmit = this.$refs.avueForm.submit;
        const originResetForm = this.$refs.avueForm.resetForm;
        const originResetFields = this.$refs.avueForm.resetFields;
        const checkAnvil = this.checkAnvil;
        const resetGrid = this.resetGrid;
        const isInGrid = this.$attrs.inGrid;

        this.$refs.avueForm.submit = function (...args) {
          originSubmit.apply(this, args);
          checkAnvil();
        };

        this.$refs.avueForm.resetForm = function (...args) {
          // this.form = {}
          originResetForm.apply(this, args);
          if (!isInGrid) {
            resetGrid();
          }
        };
      }
    },
    // 用于重置所有关联下拉框/复选框/单选框组
    resetColsDicData(list) {
      this.allColumns.map((col, index) => {
        if (list.indexOf(col.prop) > -1) {
          if (col.copyDicData) {
            this.localOptions.column[index].dicData = col.copyDicData;
          }
        }
      });
    },
    // 筛选出带有字典的组件，进行监听
    filterPropsWithOptionsRelated() {
      return this.allColumns.filter((col) => this.checkCompWithOptionRelated(col)).map((col) => col.prop);
    },
    // 判断一个组件是否配置了选项联动
    checkCompWithOptionRelated(comp) {
      let isOptionRelated = false;
      const { dicData } = comp;
      if (dicData) {
        for (let i = 0; i < dicData.length; i++) {
          const { connectChild } = dicData[i];
          if (connectChild) {
            for (let j = 0; j < connectChild.length; j++) {
              const { childprop } = connectChild[j];
              if (childprop) {
                isOptionRelated = true;
                break;
              }
            }
          }
          if (isOptionRelated) {
            break;
          }
        }
      }
      return isOptionRelated;
    },
    // 生成表单的校验规则
    generateRules(item, index) {
      const rules = [];

      if (item.isRequired === 'Y') {
        rules.push(...generateFormRules(item));
      }

      // 子表单内部 单条数据内唯一校验
      if (item.uniqe) {
        this.uniqProps.push(item.prop);
        rules.push({
          trigger: 'blur',
          validator: (rule, value, callback) => {
            this.uniqValidator(rule, value, callback, item);
          }
        });
      }
      item.rules = rules;
    },
    // 根据表单值变化更新表单校验规则
    updateRules() {
      this.options.column.map((item, index) => {
        if (item.requiredFunc) {
          try {
            const rules = [];
            rules.push(...generateFormRules(item, this.formData));

            // 子表单内部 单条数据内唯一校验
            if (item.uniqe) {
              this.uniqProps.push(item.prop);
              rules.push({
                trigger: 'blur',
                validator: (rule, value, callback) => {
                  this.uniqValidator(rule, value, callback, item);
                }
              });
            }

            item.rules = rules;
          } catch (e) {
            console.log('error!', e);
          }
        }
      });
    },
    // 校验数据唯一性
    uniqValidator(rule, value, callback, item) {
      // 找到当前组件的父
      const { parentName, prop, uniqeTip } = item;

      const anvilCodeStore = useAnvilCodeStore();
      const formData = anvilCodeStore.getPageForm(this.pageId).instance.getFormData();

      const dynamicData = formData[parentName];

      // 寻找相同prop的值集
      const values = dynamicData.map((data) => data[prop]);
      const valueLen = values.filter((v) => v == value).length;
      if (valueLen > 1) {
        callback(new Error(uniqeTip));
      } else {
        callback();
      }
    },
    // 校验所有的唯一值字段
    checkUniqFields() {
      this.uniqProps.forEach((prop) => {
        this.$refs.avueForm.validateField(prop);
      });
    },
    // 处理表单数据变化
    handleFormDataChange(newVal) {
      if (!this.formulaWatcher && newVal) {
        this.watchFormula();
      }
      if (!this.displayRulesWatcher && newVal) {
        this.watchDisplayRules();
      }
      this.watchOptionsRelated(newVal);
      this.updateRules();
      // this.setFormDefaultValue();

      if (this.isDynamicChild) {
        this.checkUniqFields();
      }
      this.$emit('update:data', newVal);
    },
    // 处理表单json变化
    handleFormJsonChange(newVal) {
      if (!this.compsRefWatcher && newVal) {
        this.watchCompsRef();
      }
    },
    // 初始化表单json
    async initFormJson() {
      this.uniqProps = [];
      const promises = [];
      this.allColumns.map((item, index) => {
        this.generateUploadUrl(item, index);
        this.generateRules(item, index);
        this.setCustomUpload(item);
        this.setFieldClassName(item);
        // 异步方法另外操作
        promises.push(this.generateSelectDicts(item, index));
      });
      await Promise.all(promises);
    },
    async initFormData() {
      await this.setFormDefaultValue();
    },
    // 根据当前的环境配置生成上传组件的url
    generateUploadUrl(item, index) {
      const { type, ajaxSetting, action } = item;
      if (type == 'upload') {
        if (!action) {
          if (!ajaxSetting || !ajaxSetting.url) {
            // anvil平台组件上传地址
            const url = this.baseUrl + '/zfs/upload';
            item.action = url;
          } else {
            item.action = ajaxSetting.url;
          }
        }
        // 获取token,当useCookie为false时，token从localstorage中获取
        if (item.headers) {
          item.headers[defaultSettings.tokenName] = 'Bearer ' + getToken();
        } else {
          item.headers = {
            [defaultSettings.tokenName]: 'Bearer ' + getToken()
          };
        }
      }
    },
    // 动态字典项组件调用接口获取字典项
    async generateSelectDicts(item, index) {
      return getDynamicCompDicts(this, item);
    },
    // 自定义上传的前置钩子
    async uploadBefore(file, done, loading, column) {
      try {
        if (column.ajaxSetting && column.ajaxSetting.hookBefore) {
          const anvilCodeStore = useAnvilCodeStore();
          // 获取当前表单实例
          const { instance } = anvilCodeStore.getPageForm(this.pageId);
          const params = instance[column.ajaxSetting.hookBefore](file);
          done(params);
        } else {
          done();
        }
      } catch (e) {
        console.log('uploadBefore error!', e);
      }
    },
    // 处理自定义的上传后结果,调用后置钩子,和成功后回调
    async uploadAfter(res, done, loading, column) {
      // console.log('column',column)
      const { prop, ajaxSetting, listType, bindAttrs } = column;
      if (res) {
        let uploadvalue = 'fileId';
        if (bindAttrs && bindAttrs.value) {
          uploadvalue = bindAttrs.value;
        }
        let resObj = getZfsUploadTrans(res, uploadvalue == 'fileId');
        // 附件上传类型为图片类型时，type必须为img才能显示
        if (listType && listType.includes('picture')) {
          resObj.type = 'img';
        }
        loading();
        if (this.formData[prop] && this.formData[prop] instanceof Array) {
          this.formData[prop].push(resObj);
        } else {
          this.formData[prop] = [resObj];
        }

        let resData = res;
        if (ajaxSetting && ajaxSetting.hookAfter) {
          const anvilCodeStore = useAnvilCodeStore();
          // 获取当前表单实例
          const { instance } = anvilCodeStore.getPageForm(this.pageId);
          resData = instance[ajaxSetting.hookAfter](resData);
        }
        // 实现成功后回调
        if (ajaxSetting && ajaxSetting.customCallback && ajaxSetting.customCallback.length) {
          executeFunctionsInOrder(ajaxSetting.customCallback, resData);
        }
      }
    },
    // 设置静态默认值，包括了设置非avue原生组件的表单默认值,原生组件设置时间默认值等
    setValueByStatic() {
      if (this.optionColumn && this.optionColumn.length) {
        this.optionColumn.map((col) => {
          const { valueType, value, prop } = col;
          // 在当前不存在表单值时进行默认值赋值
          if (typeof value !== 'boolean' && value && !this.formData[prop]) {
            console.log('正在设置静态默认值---');
            if (valueType == 'string' || valueType == 'number' || valueType == 'boolean') {
              this.formData[prop] = value;
            } else if (valueType == 'array' && value.length) {
              this.formData[prop] = value;
            }
          }
        });
      }
      if (this.allColumns && this.allColumns.length) {
        this.allColumns.map((col) => {
          // 处理时间默认值
          if (defaultDateGenerate.indexOf(col.type) > -1) {
            const { prop, defaultDateTime } = col;
            if (!this.formData[prop] && defaultDateTime) {
              this.formData[prop] = handleDefaultDateTime(col);
            }
          }
          // 处理时间区间默认值
          else if (defaultDateRangeGenerate.indexOf(col.type) > -1) {
            const { prop, defaultStartTime, defaultEndTime } = col;
            if (!this.formData[prop] && (defaultStartTime || defaultEndTime)) {
              this.formData[prop] = handleDefaultDateTimeRange(col);
            }
          }
        });
      }
    },
    // 设置包括原生组件在内组件的动态默认值,如果处于栅格布局内可能会延迟emit数据导致bug，待修复
    async setDefaultByAjax() {
      if (this.allColumns && this.allColumns.length) {
        const promises = [];
        this.allColumns.map((col) => {
          const { valueType, prop, defaultValueType, defaultValueAjax, type } = col;
          console.log('this.formData', this.formData);
          // 在当前不存在表单值时进行默认值赋值
          if (!this.formData[prop] && defaultValueType == '2' && defaultValueAjax) {
            console.log('正在设置动态默认值---');
            const { type, url, method, contentType, headers, body, response } = defaultValueAjax;
            let Headers = {},
              Body = {};

            headers.map((item) => {
              const { key, value } = item;
              Headers[key] = value;
            });

            body.map((item) => {
              const { key, value } = item;
              Body[key] = value;
            });

            const callback = (res) => {
              const value = jp.query(res, response ?? '$');
              if (value) {
                this.formData[prop] = value[0];
              }
            };

            const config = {
              url,
              method,
              contentType,
              headers: Headers,
              params: Body,
              callback
            };

            let promise = undefined;
            switch (type) {
              case 'ajax':
                promise = customApiExecute(config, { noLoading: true });
                break;
              case 'ajaxModel':
                promise = modelApiExecute(config, { noLoading: true });
                break;
              case 'ajaxLocal':
                promise = localApiExecute(config, { noLoading: true });
            }

            promises.push(promise);
          }
        });
        await Promise.all(promises);
      }
    },
    // 设置非avue原生组件的表单默认值,原生组件根据value值会自动赋值
    async setFormDefaultValue() {
      this.setValueByStatic();
      await this.setDefaultByAjax();
    },
    // 附件上传文件预览方法
    uplodaPreview(file, column, done) {
      const picReg = /(jpg|jpeg|png|gif|JPEG|JPG|PNG|GIF|webp|WEBP|img)/;
      const { type, url } = file;
      if (type && url) {
        const isPic = picReg.test(type);
        if (!isPic) {
          this.downloadUrl(url);
        } else {
          done();
        }
      } else {
        done();
      }
    },
    // async handleLifeCycles(type) {
    //   const lifecycleArr = this.lifeCycle.filter((c) => c.type == type);
    //   const promises = [];
    //   if (lifecycleArr.length) {
    //     lifecycleArr.map(async (l) => {
    //       if (type == 'mounted') {
    //         const p = this.handleMountedLifeCycle(l);
    //         promises.push(p);
    //       } else if (type == 'iframe') {
    //         this.handleIframeLifeCycle(l);
    //       }
    //     });

    //     await Promise.all(promises);
    //   }
    // },
    handleIframeLifeCycle(setting) {
      const { iframeType, compcall } = setting;
      if (iframeType == 'refresh') {
        executeFunctionsInOrder(compcall, undefined);
      }
    },
    // 批量执行
    async handleMountedLifeCycleList() {
      const compCallMap = this.getCompCallMap();
      const beforePromises = [],
        afterPromises = [];
      const { before, after } = compCallMap;
      if (before && before.length) {
        before.map(async (l) => {
          const p = this.handleMountedLifeCycle(l);
          beforePromises.push(p);
        });
      }
      await Promise.all(beforePromises);
      // 执行按照before,表单渲染,after的顺序
      this.showForm = true;
      console.log('表单渲染完成');

      if (after && after.length) {
        after.map(async (l) => {
          const p = this.handleMountedLifeCycle(l);
          afterPromises.push(p);
        });
      }

      await Promise.all(afterPromises);
    },
    // 先执行生命周期接口调用方法获取返回值，如果设置了表单回填，回填之后再进行组件渲染，然后再执行组件调用
    async handleMountedLifeCycle(setting) {
      const { action, api, method, contentType, callbackJsonPath, callback, compcall, noLoading, formFill, params: settingParams, hookBefore, hookAfter } = setting;

      const anvilCodeStore = useAnvilCodeStore();
      const { instance } = anvilCodeStore.getPageForm(this.pageId);

      const callbackFunc = (res) => {
        try {
          let data = res;
          if (hookAfter) {
            data = instance[hookAfter](data);
          }
          data = jp.query(data, callbackJsonPath ? callbackJsonPath : '$');
          console.log('lifeCycle回填前数据', data);
          // 有表单回填先执行表单回填
          if (callback == 'form' || formFill) {
            if (data && data.length) {
              this.setFormData(data[0]);
            }
          }

          if (callback == 'component' || (compcall && compcall.length)) {
            // 先合并已有数据和返回值，字段优先级返回值高于已有数据，然后作为参数传入
            const params = Object.assign({}, this.getDataOutside(), data[0]);
            executeFunctionsInOrder(compcall, params);
          }
        } catch (e) {
          console.log('error!', e);
        }
      };

      if (action.includes('ajax')) {
        let params = this.getParamsWithMerge(settingParams);
        if (hookBefore) {
          params = instance[hookBefore](params);
        }

        console.log('参数携带', params);

        const config = {
          url: api,
          method,
          contentType,
          params,
          callback: callbackFunc
        };

        switch (action) {
          case 'ajax':
            return await customApiExecute(config, { noLoading });
          case 'ajaxModel':
            return await modelApiExecute(config, { noLoading });
          case 'ajaxLocal':
            return await localApiExecute(config, { noLoading });
        }
      } else if (action == 'getData') {
        console.log('执行了getData', this.getDataOutside());
        return callbackFunc(this.getDataOutside());
      }
    },
    setCustomUpload(column) {
      const { type, ajaxSetting } = column;
      if (type == 'upload' && ajaxSetting && ajaxSetting.type == 'ajax') {
        column.httpRequest = (Data) => {
          customUploadByApi(this, Data.file, ajaxSetting);
        };
      }
    },
    // 根据参数设置获取合并完整的参数对象
    getParamsWithMerge(option) {
      // 兼容老数据
      if (!option || typeof option !== 'object') {
        return { ...this.getDataOutside() };
      }
      const { contantParams, compParams, withFormData } = option;

      let Params = {};
      if (contantParams && contantParams.length) {
        contantParams.map((p) => {
          const { key, value } = p;
          Params[key] = value;
        });
      }

      if (compParams && compParams.length) {
        compParams.map((p) => {
          try {
            const { key, value } = p;
            const data = this.getDataOutside();
            Params[key] = jp.query(data, value ? value : '$')[0];
          } catch (e) {
            console.log('getParamsWithMerge error!', e);
          }
        });
      }

      // 如果withFormData为false，则不合并已有数据
      if (withFormData !== false) {
        const data = { ...this.getDataOutside(), ...this.$route.query };
        Params = Object.assign({}, data, Params);
      }

      return Params;
    },
    watchDisplayRules() {
      if (isExistDisplayRule(this.options)) {
        this.displayRulesWatcher = this.$watch(
          'formData',
          debounceWrapper(function () {
            // 用全局变量记录表单值
            const windowVars = [];
            for (let key in this.formData) {
              window[key] = this.formData[key];
              windowVars.push(key);
            }
            this.options.displayRules.map((r) => {
              try {
                const { enable, type, fields, rules } = r;
                if (!enable) {
                  return;
                }
                // const fields = r.fields;
                const rootRule = rules[0];
                const rule = getDisplayRule(rootRule);
                console.log('当前表单显隐/启用规则为', rule);
                const res = eval(rule);
                console.log('当前表单显隐/启用规则判断结果为', res);
                if (!type || type == 'display') {
                  res ? setCompsRefShow(this.allColumns, fields) : initCompsRef(this.allColumns, fields);
                } else {
                  res ? setCompsRefEnable(this.allColumns, fields) : initDisabledCompsRef(this.allColumns, fields);
                }
              } catch (e) {
                console.log(e);
                return;
              }
            });
            console.log('目前的全局变量', windowVars);
            windowVars.map((v) => {
              delete window[v];
            });
          }),
          {
            deep: true
          }
        );
      }
    },
    // 根据数据校验规则id执行校验
    operateValidateRules(ruleIds) {
      // 用全局变量记录表单值
      const windowVars = [];
      for (let key in this.formData) {
        window[key] = this.formData[key];
        windowVars.push(key);
      }
      // 记录校验结果
      let result = true;
      this.options.validateRules.map((r) => {
        try {
          if (ruleIds.indexOf(r.uuid) === -1) {
            return;
          }
          const rootRule = r.rules[0];
          const rule = getDisplayRule(rootRule);
          console.log('当前表单数据校验规则为', rule);
          const res = eval(rule);
          console.log('当前表单数据校验规则判断结果为', res);
          const { message, type, style } = r;
          if (res) {
            result = false;
            switch (style) {
              case 'message':
                ElMessage({
                  message,
                  type
                });
                break;
              case 'messageBox':
                ElMessageBox.alert(message, '提示', {
                  confirmButtonText: '确定',
                  type
                });
                break;
              case 'notification':
                ElNotification({
                  title: '提示',
                  message,
                  type
                });
                break;
            }
          }
        } catch (e) {
          this.msgError(e);
          result = false;
        }
      });
      console.log('目前的全局变量', windowVars);
      windowVars.map((v) => {
        delete window[v];
      });
      return result;
    },
    // 根据组件类型判断是否提供formdata参数
    isProvideFormData(type) {
      const types = provideFormData;
      return types.indexOf(type) > -1;
    },
    // 根据页面载入时中的组件调用列表判断执行的时机，如果有组件调用，则在页面渲染后执行，如果没有则在渲染前执行完毕,返回对象
    getCompCallMap() {
      const compCallMap = {
        before: [],
        after: []
      };
      this.lifeCycle
        .filter((c) => c.type == 'mounted')
        .map((life) => {
          const { compcall } = life;
          if (compcall && compcall.length) {
            compCallMap.after.push(life);
          } else {
            compCallMap.before.push(life);
          }
        });
      return compCallMap;
    },
    setFieldClassName(item) {
      if (item.classNames && item.classNames.length) {
        item.className = item.classNames.join(' ') + (item.className ? ' ' + item.className : '');
      }
    }
  }
};
</script>

<style lang="scss" scoped>
:deep(.w-e-full-screen-container) {
  z-index: 1;
}
</style>
